// SPDX-FileCopyrightText: Adam Evyčędo
//
// SPDX-License-Identifier: GPL-3.0-or-later

package xyz.apiote.bimba.czwek.data.sources.feeds

import android.content.Context
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import com.github.jershell.kbson.KBson
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import xyz.apiote.bimba.czwek.settings.feeds.FeedSettings
import xyz.apiote.bimba.czwek.settings.feeds.FeedsSettings
import java.io.File

class FeedsOfflineDataSource {
	companion object {
		const val TRANSITOUS_FILE = "transitous"
		const val GEOCODING_FILE = "geocoding"
		const val NO_GEOCODING_DATA_SHOWN = "no_geocoding_data_shown"
		const val DIRECTORY = "feeds_settings"
	}

	private fun readFile(settingsFile: File): Flow<Pair<String, FeedSettings>> = flow {
		if (!settingsFile.exists()) {
			return@flow
		}

		KBson().load(FeedsSettings.serializer(), settingsFile.readBytes()).settings.forEach {
			emit(Pair(it.key, it.value))
		}
	}

	private fun readFileList(settingsFile: File): Map<String, FeedSettings> {
		val settings = mutableMapOf<String, FeedSettings>()
		if (!settingsFile.exists()) {
			return settings
		}

		KBson().load(FeedsSettings.serializer(), settingsFile.readBytes()).settings.forEach {
			settings[it.key] = it.value
		}
		return settings
	}

	private fun readFileSingle(settingsFile: File): FeedSettings? {
		if (!settingsFile.exists()) {
			return null
		}

		return try {
			KBson().load(FeedSettings.serializer(), settingsFile.readBytes())
		} catch (_: NoSuchElementException) {
			null
		}
	}

	private fun writeFile(settingsFile: File, settings: FeedsSettings) {
		settingsFile.writeBytes(KBson().dump(FeedsSettings.serializer(), settings))
	}

	private fun writeFileSingle(settingsFile: File, settings: FeedSettings) {
		settingsFile.writeBytes(KBson().dump(FeedSettings.serializer(), settings))
	}

	fun getFeeds(serverID: String, context: Context): Map<String, FeedSettings> {
		return readFileList(File(File(context.filesDir, DIRECTORY), serverID))
	}

	fun getTransitous(context: Context): FeedSettings? {
		return readFileSingle(File(File(context.filesDir, DIRECTORY), TRANSITOUS_FILE))
	}

	fun getGeocoding(context: Context): FeedSettings? {
		return readFileSingle(File(File(context.filesDir, DIRECTORY), GEOCODING_FILE))
	}

	fun setFeeds(serverID: String, settings: FeedsSettings, context: Context) {
		val dir = File(context.filesDir, DIRECTORY)
		val dirMade = dir.mkdirs()
		if (!dirMade && !dir.exists()) {
			throw IllegalStateException("cannot mkdir ${context.filesDir}/$DIRECTORY")
		}
		writeFile(File(dir, serverID), settings)
	}

	fun setTransitous(settings: FeedSettings, context: Context) {
		val dir = File(context.filesDir, DIRECTORY)
		val dirMade = dir.mkdirs()
		if (!dirMade && !dir.exists()) {
			throw IllegalStateException("cannot mkdir ${context.filesDir}/$DIRECTORY")
		}
		writeFileSingle(File(dir, TRANSITOUS_FILE), settings)
	}

	fun setGeocoding(settings: FeedSettings, context: Context) {
		val dir = File(context.filesDir, DIRECTORY)
		val dirMade = dir.mkdirs()
		if (!dirMade && !dir.exists()) {
			throw IllegalStateException("cannot mkdir ${context.filesDir}/$DIRECTORY")
		}
		writeFileSingle(File(dir, GEOCODING_FILE), settings)
	}

	fun getGeocodingInfoShown(context: Context): Boolean {
		return PreferenceManager.getDefaultSharedPreferences(context)
			.getBoolean(NO_GEOCODING_DATA_SHOWN, false)
	}

	fun setGeocodingInfoShown(isShown: Boolean, context: Context) {
		PreferenceManager.getDefaultSharedPreferences(context).edit {
			putBoolean(NO_GEOCODING_DATA_SHOWN, isShown)
		}
	}
}